import logging
import socket
import queue
from collections import Counter
from threading import Thread, Event
from flask_cors import CORS
from flask import Flask, Response, request
import sys
from SubFunction import *
from inference import GenModule
from dataStore import GlobalVar
from util import get_camera_list
logger = logging.getLogger("yolov5")
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)

logger.addHandler(handler)
logger.addHandler(console)

import configparser
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
cf = configparser.ConfigParser()
cf.read(os.path.join(BASE_DIR,"config.ini"), encoding='UTF-8')
front_weight=cf.get("weight","front_weight")
back_weight=cf.get("weight","back_weight")


class Appback:
    def __init__(self, gpu_id):
        self.app = Flask(__name__)
        self.setup_routes()
        CORS(self.app)
        self.program = {}
        self.send_data = None
        self.personTrack = False
        self.src_list = []
        self.imagesize = 640
        self.person_type = 2
        self.device = gpu_id
        self.camera_list = []
        self.exe_camera_list=[]
        self.interval_frame = 0
        self.camera_map = {}
        self.thread_wait = False
        self.started_evt = Event()
        self.is_class = 0
        self.frameNum = 1
        self.tea_port=0
        self.func_dict = {
            '1': GenModule,  # 学生
            '2': GenModule,  # 教师
        }
        self.weights_dict = {
            '1': [os.path.join(BASE_DIR,front_weight)],
            '2': [os.path.join(BASE_DIR,back_weight)],
        }

    def run(self, host, port):
        print("appteacher")
        self.tea_port=port
        print(self.tea_port)
        self.app.run(host=host, port=port)


    # 有队列
    # def gen1(self,camera_id,type):
    #     while True:
    #         if len(self.camera_map) != 0:
    #             queue_length = self.camera_map[type].qsize()
    #             # print("摄像头{}前-->队列的长度为{}:".format(camera_id,queue_length))
    #             # if queue_length <= 5:
    #             #     # time.sleep(0.3)
    #             #     pass
    #             frame = self.camera_map[type].get()
    #             # time.sleep(0.19)
    #             queue_length = self.camera_map[type].qsize()
    #             # print("摄像头{}后-->队列的长度为{}:".format(camera_id,queue_length))
    #         else:
    #             frame = 2
    #             frame.to_bytes(4, byteorder='little', signed=True)
    #         # 使用generator函数输出视频流， 每次请求输出的content类型是image/jpeg
    #         # print(frame)
    #         yield (b'--frame\r\n'
    #                b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
    # 有队列
    # def workThred(self, hoisting, person_type, started_evt):
    #     print('countdown starting')
    #     data_store = GlobalVar()
    #     # import websockets
    #     for i in self.camera_list:
    #         self.camera_map[f"gas:video:{i}:name"] = queue.Queue()
    #
    #     while True:
    #         if self.thread_wait:
    #             started_evt.wait()
    #             # print("主线程暂停")
    #             continue
    #         start_time = time.time()
    #         # 检测每一帧的检测结果[L,NL]
    #         hoisting.execute_func()
    #
    #         # 每一帧的画面
    #         for key, value in hoisting.camera_map.items():
    #             self.camera_map[key].put(value)
    #         # self.camera_map = hoisting.camera_map
    #         # queue_length = self.camera_map[f"gas:video:{self.camera_list[0]}:name"].qsize()
    #         # print("112-->队列的长度为:", queue_length)
    #         # if(queue_length == 30):
    #         for key, value in hoisting.camera_map.items():
    #             if self.camera_map[key].qsize() >= 30:
    #                 self.camera_map[key].get()
    #         hoisting.class_is = self.is_class
    #         # 判断是否上下课，并发送图片
    #         if hoisting.class_is == 1:  # 下课
    #             hoisting.clear_variable()
    #             self.is_class = 0
    #         if hoisting.class_is == 2:
    #             if person_type == '2':  # 上课
    #                 hoisting.send_points()
    #             self.is_class = 0
    #
    #         # Thread(target=hoisting.senf_m).start()
    #         # hoisting.senf_m()
    #         end_time = round(time.time() - start_time, 3)
    #         # self.frameNum = self.frameNum + 1
    #         # print(f"第{self.frameNum - 1}帧")
    #         # print("帧总的推理时间：", end_time)
    #         # else:
    #         #     print("网络已中断，请检测网络连接................")

    # 没有队列
    def gen1(self,camera_id, type):
        while True:
            if len(self.camera_map) != 0:
                # if self.secret == False:
                # time.sleep(0.15)
                frame = self.camera_map[type]
            else:
                frame = 2
                frame.to_bytes(4, byteorder='little', signed=True)
            # 使用generator函数输出视频流， 每次请求输出的content类型是image/jpeg
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
    # 没有队列
    def workThred(self,hoisting, person_type, started_evt):
        print('countdown starting')
        num = 0
        while True:
            if self.thread_wait:
                self.started_evt.wait()
                print("主线程暂停")

                # 在此添加退出前要做的工作，如保存文件等
                # 新
            # start_time = time.time()
            self.send_data = hoisting.execute_func()
            # time.sleep(hoisting.sleeptime)
            self.camera_map = hoisting.camera_map
            # print(f"{hoisting.port},时间：",time.time() - start_time)
            hoisting.class_is = self.is_class
            # 判断是否上下课，并发送图片
            if hoisting.class_is == 1:
                hoisting.clear_variable()
                self.is_class = 0
            if hoisting.class_is == 2:
                if self.person_type == '2':
                    hoisting.send_points()
                self.is_class = 0
            # if not hoisting.q.empty():
            #     Thread(target=hoisting.senf_m).start()
            # Thread(target=hoisting.senf_m).start()
            # end_time = round(time.time() - start_time, 3)
            num = num + 1
            # print(f"总的推理时间：", end_time)
            # else:
            #     print("网络已中断，请检测网络连接................")


    def workthread1(self,hoisting, names):
        while True:
            hoisting.resutl_save(names)


    def workthread2(self,hoisting):
        while True:
            hoisting.save_img()

    def isNetChainOK(self,testserver):
        s = socket.socket()
        s.settimeout(3)
        try:
            status = s.connect_ex(testserver)
            if status == 0:
                s.close()
                return True
            else:
                return False
        except Exception as e:
            return False


    def judgeNet(self,testserver=('www.baidu.com', 443)):
        isOK = self.isNetChainOK(testserver)
        return isOK

    def common_fun(self,hoisting, person_type):
        print("开始执行")
        t = Thread(target=self.workThred, args=(hoisting, person_type, self.started_evt), daemon=True)
        t.start()
        print('countdown is running')
        data = {
            "code": 200
        }
        return json.dumps(data)
    def setup_routes(self):
        @self.app.route('/isLive',methods=['GET', 'POST'])#判断这个flask进程是否存在
        def is_live():
            data = {
                "code": 200,
                "msg": "isLive",
                "data": {}
            }
            return json.dumps(data)
        @self.app.route('/recover', methods=['GET'])
        def recover():
            self.started_evt.set()
            data = {
                "code": 200,
                "msg": "主线程恢复",
                "data": {}
            }
            return json.dumps(data)


        @self.app.route('/get_stream', methods=['GET', 'POST'])  # 这个地址返回视频流响应
        def test_redis():
            alarm_type = request.args.get("type")
            print("视频流参数：", alarm_type)
            camera_id=alarm_type.split("gas:video:")[1].split(":")[0]
            return Response(self.gen1(camera_id,alarm_type), mimetype='multipart/x-mixed-replace; boundary=frame')

        @self.app.route('/class_begin', methods=['GET'])
        def class_begin():
            self.is_class = 1
            data = {
                "code": 200,
                "msg": "success",
                "data": {}
            }
            return json.dumps(data)

        @self.app.route('/class_end', methods=['GET'])
        def class_end():
            self.is_class = 2
            data = {
                "code": 200,
                "msg": "success",
                "data": {}
            }
            return json.dumps(data)

        @self.app.route('/getBehaviorNum', methods=['GET', 'POST'])
        def getbehaviornum():
            camera_id = request.args.get("camera_id")
            print("camera_id:::::", camera_id)
            f = self.camera_list.index(camera_id)
            data = self.send_data[f]
            send_json = {
                "camera_id": camera_id,
                "learing": 0,
                'hand': 0,
                "sleep": 0,
                "stand": 0,
                "phone": 0
            }
            data = np.array(data)
            data_json = Counter(data)
            send_json["camera_id"] = camera_id
            if data_json["L"]:
                send_json["learing"] = data_json["L"]
            if data_json["hand"]:
                send_json["hand"] = data_json["hand"]
            if data_json["sleep"]:
                send_json["sleep"] = data_json["sleep"]
            if data_json["stand"]:
                send_json["stand"] = data_json["stand"]
            if data_json["phone"]:
                send_json["phone"] = data_json["phone"]
            print("-------正在统计当前人数--------")
            data = {
                "code": 200,
                "msg": "数据获取成功",
                "data": send_json}
            return json.dumps(data)

        @self.app.route('/stop', methods=["GET"])  # 这个地址返回视频流响应
        def stop():
            self.thread_wait = True
            print("结束执行")
            data = {
                "code": 200,
                "msg": "算法结束",
                "data": {}
            }
            return json.dumps(data)

        @self.app.route('/start', methods=['POST', 'GET', 'OPTIONS'])  # 这个地址返回视频流响应
        def start():
            # if request.method == 'OPTIONS':
            #     # 处理 OPTIONS 请求
            #     response_headers = {
            #         'Access-Control-Allow-Origin': '*',
            #         'Access-Control-Allow-Methods': 'POST',
            #         'Access-Control-Allow-Headers': 'Content-Type'
            #     }
            #     return ('', 204, response_headers)
            # data = request.json
            # print(data)
            data = request.get_data()
            # data=get_camera_list(self.tea_port)  #正式运行时打开这个，从后端获取视频流数据
            data = json.loads(data)
            print("daa:::::::::::;", data)
            for data_in in data:
                if data_in['camera_id'] not in self.camera_list:
                    self.src_list.append(data_in['path'])
                    self.camera_list.append(data_in['camera_id'])
                    self.exe_camera_list.append(data_in['camera_id'])
                    self.person_type = data_in["person_type"]
            if len(self.exe_camera_list) > 0:
                self.personTrack=True
                self.imagesize=640
                Func = self.func_dict[str(self.person_type)]  # 类
                sub_weight = self.weights_dict[str(self.person_type)]  # 权重
                sub_addr = self.src_list
                params = {"camera_id": 0, "created_at": "", "data_id": "", 'data': "", "person_type": str(self.person_type),
                          "event_level": "", "event_type": "", "screenshot_url": "", "video_url": ""}
                sub_func = GenModule(src_list=sub_addr,  # 视频源
                                    weight=sub_weight,  # 权重
                                    params=params,
                                    tea_port=self.tea_port,
                                    fps_show=False,  # fps显示 # 丢帧模拟
                                    track=self.personTrack,  # 跟踪
                                    msg_send=True,  # 警报发送
                                    imagesize=self.imagesize,
                                    half=True,
                                    camera_list=self.exe_camera_list,  # 摄像头数组
                                    Time_time=0,  # 隔多少帧检测一次
                                    device=self.device,
                                    COUNTS=5,  # 间隔30帧
                                    FramesListening=60,  # 听讲人数，间隔5秒
                                    FramesPeople=5,  # 教室人数，间隔一分钟
                                    # secret=False
                                )

                status = self.common_fun(hoisting=sub_func, person_type=self.person_type)
                return status
if __name__ == '__main__':
    gpu_id = sys.argv[1]
    host=sys.argv[2]
    port=sys.argv[3]
    # gpu_id = 0
    # host='0.0.0.0'
    # port=5030
    Appback(gpu_id).run(host=host, port=port)
